/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package testing.jee.web.view;

import com.vaadin.data.Item;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.util.PropertyFormatter;
import com.vaadin.data.validator.AbstractValidator;
import com.vaadin.data.validator.StringLengthValidator;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.event.ShortcutListener;
import com.vaadin.ui.AbstractSelect.NewItemHandler;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.DateField;
import com.vaadin.ui.DefaultFieldFactory;
import com.vaadin.ui.Embedded;
import com.vaadin.ui.Field;
import com.vaadin.ui.Form;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import testing.jee.ejb.RequestBean;
import testing.jee.entity.Timeline;
import testing.jee.entity.User;
import testing.jee.entity.Workday;
import testing.jee.entity.Workpackage;
import testing.jee.util.DateUtils;
import testing.jee.util.DurationUtil;
import testing.jee.web.View;

/**
 *
 * @author kreisera
 */
@org.springframework.stereotype.Component
@Scope(value = "session")
public class NewWorkpackageView extends HorizontalLayout implements View {

    @Autowired
    RequestBean req;
    private Form workpackageForm = new Form();
    Workpackage workpackage = new Workpackage();
    VerticalLayout dayOverViewLayout = new VerticalLayout();
    private String[] visibleProperties = new String[]{"label", "description", "dueDate", "duration"};
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");

    @PostConstruct
    public void init() {
        workpackageForm.setCaption("New Workpackage");
        workpackageForm.setWriteThrough(false);
        workpackageForm.setInvalidCommitted(false);
        workpackageForm.setFormFieldFactory(new WorkpackageFieldFactory());
        workpackage.setDuration(8);
        BeanItem<Workpackage> workBeanItem = new BeanItem<Workpackage>(workpackage, visibleProperties);
        workpackageForm.setItemDataSource(workBeanItem);
        workpackageForm.getField("duration").setPropertyDataSource(new PropertyFormatter(workpackageForm.getField("duration").getPropertyDataSource()) {

            @Override
            public String format(Object value) {
                return DurationUtil.serializeDuration((Integer) value);
            }

            @Override
            public Object parse(String formattedValue) throws Exception {
                return (Integer) DurationUtil.convertToHours(formattedValue);
            }
        });
        Button submit = new Button("Add");
        HorizontalLayout footer = new HorizontalLayout();
        footer.addComponent(submit);
        submit.addListener(new Button.ClickListener() {

            @Override
            public void buttonClick(ClickEvent event) {
                submitForm();
            }
        });
        workpackageForm.setFooter(footer);
        workpackageForm.addShortcutListener(new ShortcutListener("Submit", KeyCode.ENTER, null) {

            @Override
            public void handleAction(Object sender, Object target) {
                submitForm();
            }
        });
        addComponent(new Embedded());
        HorizontalLayout formAndOverViewLayout = new HorizontalLayout();
        formAndOverViewLayout.setSpacing(true);
        formAndOverViewLayout.addComponent(workpackageForm);
        formAndOverViewLayout.addComponent(dayOverViewLayout);
        addComponent(formAndOverViewLayout);
        addComponent(new Embedded());
        setComponentAlignment(formAndOverViewLayout, Alignment.MIDDLE_CENTER);
        setSpacing(true);
        setWidth("100%");
        addStyleName("wp-workpackage-view");
    }

    @Override
    public void postView() {
        workpackageForm.focus();
    }

    @Override
    public void preView() {
        createDayOverview();
    }

    private void createDayOverview() {
        dayOverViewLayout.removeAllComponents();
        Label titleLabel = new Label("Today, " + dateFormat.format(DateUtils.normalize(new Date())));
        titleLabel.setStyleName("rp-bold");
        dayOverViewLayout.addComponent(titleLabel);
        for (User u : req.listUsers()) {
            VerticalLayout userAndWorkpackage = new VerticalLayout();
            userAndWorkpackage.setSpacing(false);
            userAndWorkpackage.setStyleName("rp-day-overview-box");
            userAndWorkpackage.setWidth("200px");
            dayOverViewLayout.addComponent(userAndWorkpackage);
            Label userLabel = new Label(u.getId());
            userAndWorkpackage.addComponent(userLabel);
            Timeline timeline = req.getTimeline(DateUtils.normalize(new Date()), DateUtils.normalize(new Date()), u);
            for (Date currDate : timeline.getDates()) {
                Workday workDay = timeline.getWorkday(currDate);
                StringBuilder workpackageString = new StringBuilder();
                Iterator<Workpackage> it = workDay.getWorkpackages().iterator();
                while (it.hasNext()) {
                    workpackageString.append(it.next().getLabel());
                    if (it.hasNext()) {
                        workpackageString.append(", ");
                    }
                }
                if(workpackageString.length() == 0)
                    workpackageString.append("-");
                Label workpackageLabel = new Label(workpackageString.toString(), Label.CONTENT_RAW);
                workpackageLabel.setStyleName("rp-day-overview-wp");
                userAndWorkpackage.addComponent(workpackageLabel);
            }
        }
    }

    private class WorkpackageFieldFactory extends DefaultFieldFactory {

        @Override
        public Field createField(Item item, Object propertyId, Component uiContext) {
            Field field = super.createField(item, propertyId, uiContext);
            if ("label".equals(propertyId)) {
                final ComboBox label = new ComboBox();
                label.setCaption("Label");
                label.setRequired(true);
                label.setRequiredError("Please insert a label!");
                label.setNewItemsAllowed(true);
                label.setImmediate(true);
                label.setNewItemHandler(new NewItemHandler() {

                    @Override
                    public void addNewItem(String newItemCaption) {
                        label.addItem(newItemCaption);
                        label.setValue(newItemCaption);
                    }
                });
                label.addValidator(new StringLengthValidator("Label must be between 3 and 15 characters", 3, 15, false));
                for (String suggestion : req.suggestWorkpackageNames(null)) {
                    label.addItem(suggestion);
                }
                field = label;
            } else if ("description".equals(propertyId)) {
                TextArea description = new TextArea();
                description.setCaption("Description");
                description.setNullRepresentation("");
                field = description;
            } else if ("dueDate".equals(propertyId)) {
                DateField dueDate = (DateField) field;
                dueDate.setRequired(true);
                dueDate.setRequiredError("Please provide a due date!");
                dueDate.setDateFormat("dd.MM.yyyy");
                dueDate.addValidator(new AbstractValidator("Due date must be in the future!") {

                    @Override
                    public boolean isValid(Object value) {
                        Date date = (Date) value;
                        Date now = new Date();
                        if (date.after(now)) {
                            return true;
                        }
                        return false;
                    }
                });
            } else if ("duration".equals(propertyId)) {
                TextField duration = (TextField) field;
                duration.setRequired(true);
                duration.setDescription("Amount of hours needed to complete this workpackage - use \"h\" for hours and \"d\" as shortcut for days (e.g.: \"4h\" or \"1d 6h\")");
                duration.addValidator(new DurationValidator("Please provide a valid duration greater than zero"));
            }
            return field;
        }
    }

    private void submitForm() {
        workpackageForm.commit();
        req.createWorkpackage(workpackage);
        getApplication().getMainWindow().showNotification("Workpackage \"" + workpackage.getLabel() + "\" created successfully!");
        workpackage = new Workpackage();
        workpackage.setDuration(8);
        workpackageForm.setItemDataSource(new BeanItem<Workpackage>(workpackage, visibleProperties));
        workpackageForm.getField("duration").setPropertyDataSource(new PropertyFormatter(workpackageForm.getField("duration").getPropertyDataSource()) {

            @Override
            public String format(Object value) {
                return DurationUtil.serializeDuration((Integer) value);
            }

            @Override
            public Object parse(String formattedValue) throws Exception {
                return (Integer) DurationUtil.convertToHours(formattedValue);
            }
        });
        workpackageForm.focus();
        createDayOverview();
    }
}
